package com.jiangds.open.check.spring.aop;

import com.jiangds.open.annotation.NeedCheck;
import com.jiangds.open.check.spring.CheckProperties;
import org.aopalliance.aop.Advice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.AbstractPointcutAdvisor;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * {@link CheckAdvisor}  TODO 请将该类加一个说明
 *
 * @author jiangliang
 * @since 2021/1/8 14:56
 */
public class CheckAdvisor extends AbstractPointcutAdvisor {

    private final CheckProperties properties;

    private Pointcut pointcut;

    private Advice advice;

    public CheckAdvisor(CheckProperties properties, Advice advice) {
        pointcut = new CheckPoint();
        this.advice = advice;
        this.properties = properties;
    }

    @Override
    public Pointcut getPointcut() {
        return pointcut;
    }

    @Override
    public Advice getAdvice() {
        return advice;
    }


    private class CheckPoint implements Pointcut {

        @Override
        public ClassFilter getClassFilter() {
            return  classFilter->classFilter.getPackage().getName().equals(properties.getPackageName());
        }

        @Override
        public MethodMatcher getMethodMatcher() {
            return new CheckMethodFilter();
        }
    }

    private class CheckMethodFilter implements MethodMatcher {

        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            if(Modifier.isPublic(method.getModifiers())){
                Annotation[][] parameterAnnotations = method.getParameterAnnotations();
                for (Annotation[] parameterAnnotation : parameterAnnotations) {
                    for (Annotation annotation : parameterAnnotation) {
                        if(annotation.annotationType() == NeedCheck.class){
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        @Override
        public boolean isRuntime() {
            return false;
        }

        @Override
        public boolean matches(Method method, Class<?> targetClass, Object... args) {
            return false;
        }
    }
}
